package assdraw2.canvas.presentation;


import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;

import assdraw2.canvas.CanvasControl;
import assdraw2.canvas.abstraction.CanvasShapeModel;
import assdraw2.canvas.abstraction.Shape;
import assdraw2.common.MessageType;
import assdraw2.common.PACMessage;
import assdraw2.common.PresentationWindowListener;



public class CanvasPresentation extends JFrame implements MouseListener, MouseMotionListener, KeyListener{


		private static final long serialVersionUID = 1L;
		
	    private CanvasControl canvasControl;
	    
	    AffineTransform transformer = new AffineTransform();	    	   
	    
	    private Visitor currentVisitor;

		private double zoomFactor = 1.0;
		private double translationX = 0.0;
		private double translationY = 0.0;
		
	    
	    public CanvasPresentation(CanvasControl control, CanvasShapeModel d)
	    {
	        super("Canvas");	        
	        
	        this.setPreferredSize(new Dimension(400,400));
	        this.pack();
	        setLocation(50,100);
	        this.setVisible(true);
	        
	        canvasControl = control;
	    	canvasControl.setCanvasModel(d);        
	        
	        setFocusable(true);
	        setFocusTraversalKeysEnabled(false);
	        	        
	        addMouseListener(this);
	        addKeyListener(this);
	        addWindowListener(new PresentationWindowListener(canvasControl));
	    }

	    @Override	
	    public void paint(Graphics g)
	    {
	    	g.clearRect(0, 0, this.getWidth(), this.getHeight());
	    	//g.drawLine(0, 0, 200, 200);
	    	    	
	    	AffineTransform transformer = new AffineTransform();
	    	transformer.scale(zoomFactor, zoomFactor);
	    	transformer.translate(translationX, translationY);    	    	    
	    	Graphics2D g2d = (Graphics2D)g;
	    	g2d.setTransform(transformer);
	    	    	
	    	currentVisitor = new ShapeDrawVisitor(g2d);	    	
	        
	        for(Shape s : canvasControl.getShapeModel().getShapes()) {
	            
	            if(canvasControl.getSelection().contains(s)){
	            	((ShapeDrawVisitor)currentVisitor).setInSelection(true);
	            }else{
	            	((ShapeDrawVisitor)currentVisitor).setInSelection(false);
	            }
	            
	            s.accept(currentVisitor);
	            
	        }
	        
	    }   
	    	

	    
	    /**
	     * Selects or deselects the rectangle
	     * @param r Rectangle
	     */    
		public void addToSelection(Shape s) {
			if(! canvasControl.getSelection().contains(s))
				canvasControl.getSelection().add(s);
			
			repaint();
		}
	    
	    @Override
	    public void mouseClicked(MouseEvent e)
	    {
	    	canvasControl.mouseClicked(getRealMouseX(e), getRealMouseY(e));
	    	
	    }

		@Override
	    public void mouseReleased(MouseEvent e)
	    {
	    	if(getMouseMotionListeners().length==1)
	    		removeMouseMotionListener(getMouseMotionListeners()[0]);
	    }
	    
	    @Override
	    public void mouseEntered(MouseEvent e)
	    {
	        
	    }
	    
	    @Override
	    public void mouseExited(MouseEvent e)
	    {
	        
	    }
	    
	    @Override
	    public void mousePressed(MouseEvent e)
	    {
	    	canvasControl.mousePressed(getRealMouseX(e), getRealMouseY(e));
	    }
	    
	    
		@Override
		public void mouseDragged(MouseEvent e) {

			canvasControl.mouseDragged(getRealMouseX(e), getRealMouseY(e));
			
			repaint();
		}

		@Override
		public void mouseMoved(MouseEvent arg0) {

		}
		@Override
		public void keyPressed(KeyEvent e) {
			if(e.getKeyCode() == KeyEvent.VK_LEFT){
				translationX += 5;
			}else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
				translationX -= 5;
			}else if(e.getKeyCode() == KeyEvent.VK_UP){
				translationY += 5;
			}else if(e.getKeyCode() == KeyEvent.VK_DOWN){
				translationY -= 5;
			}
			repaint();
		}
		@Override
		public void keyTyped(KeyEvent e) {
			
		}
		
		@Override
		public void keyReleased(KeyEvent e) {
			
			if(!canvasControl.getSelection().isEmpty()){
				if(e.getKeyCode() == KeyEvent.VK_B){
					for(Shape s : canvasControl.getSelection())
						canvasControl.getShapeModel().sendToBack(s);
					return;
				}else if(e.getKeyCode() == KeyEvent.VK_F){
					for(Shape s : canvasControl.getSelection())
						canvasControl.getShapeModel().bringToFront(s);
					return;
				}else if(e.getKeyCode() == KeyEvent.VK_DELETE){
					for(Shape s : canvasControl.getSelection())
						canvasControl.getShapeModel().removeShape(s);
					canvasControl.getSelection().clear();
					return;
				}
			}
			
		}

		public void zoomOut() {
			zoomFactor *= 0.9;
			repaint();
		}

		public void zoomIn() {
			zoomFactor *= 1.1;
			repaint();
		}
		
	    private int getRealMouseX(MouseEvent e) {
			return (int)Math.round(e.getX()/zoomFactor - translationX);
		}
	    
	    private int getRealMouseY(MouseEvent e) {
			return (int)Math.round(e.getY()/zoomFactor - translationY);
		}

	
	public void close() {
		dispose();
		canvasControl.sendMessage(new PACMessage(MessageType.CLOSE));
	}

}
